package vip.mtdp.util;

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Hashtable;

import javax.imageio.ImageIO;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;

/**
 * 
 *
 * @Description 二维码生成工具
 * @author gqwang
 * @date 2016年2月18日下午3:20:24
 *
 */
public class QRCodeUtil {
	
	public static byte[] getQRCode(String str,String imageType,int width,int height,byte[] logo){
		return getQRCode(str, imageType, width, height, 0, logo);
	}
	
	/**
	 * 根据传入的参数生成二维码图片返回字节数组
	 * @param str
	 * @return
	 */
	public static byte[] getQRCode(String str,String imageType,int width,int height,int margin,byte[] logo){
		byte[] resultByte = null;
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		try {
			BitMatrix bitMatrix = new MultiFormatWriter().encode(changeEncodType(str), BarcodeFormat.QR_CODE, width, height,getQREncodeHintType(margin));
			//先生成二维码
			BufferedImage image = bitToImage(bitMatrix);
			if(null != logo && logo.length > 0){
				//再添加logo
				Image logoImage = ImageIO.read(new ByteArrayInputStream(logo));
				Graphics2D g = image.createGraphics();
				compressLogoImage(image, logoImage);
				// logo宽高
				int mWidth = logoImage.getWidth(null);
				int mHeight = logoImage.getHeight(null);
				// logo起始位置，此目的是为logo居中显示
				int x = (image.getWidth() - mWidth) / 2;
				int y = (image.getHeight() - mHeight) / 2;
				g.drawImage(logoImage, x, y, mWidth, mHeight, null);
				g.dispose();
			}
			boolean b = ImageIO.write(image, imageType, bos);
			if(!b){
				throw new RuntimeException("生成二维码出错");
			}
		} catch (WriterException e) {
			throw new RuntimeException("生成二维码出错",e);
		} catch (IOException e) {
			throw new RuntimeException("生成二维码出错",e);
		}
		resultByte = bos.toByteArray();
		return resultByte;
	}
	
	/**
	 * 将bit转换成image
	 * @param bitMatrix
	 * @return
	 */
	private static BufferedImage bitToImage(BitMatrix bitMatrix){
		if(bitMatrix == null){
			return null;
		}
		int width = bitMatrix.getWidth();
		int height = bitMatrix.getHeight();
		BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
		//填充图片
		for(int x = 0; x < width; x++){
			for(int y = 0; y < height; y++){
				image.setRGB(x, y, bitMatrix.get(x, y) ? TdpUtilConstant.COLOR_BLACK : TdpUtilConstant.COLOR_WHITE);
			}
		}
		return image;
	}
	
	/**
	 * 转码
	 * @param str
	 * @return
	 */
	private static String changeEncodType(String str){
		try {
			return new String(str.getBytes(TdpUtilConstant.CHARACTER_UTF_8),TdpUtilConstant.CHARACTER_ISO_8859_1);
		} catch (UnsupportedEncodingException e) {
			return str;
		}
	}
	
	/**
	 * 设置QR二维码参数
	 * @param margin 二维码边框 默认0
	 * @return
	 */
	private static Hashtable<EncodeHintType, Object> getQREncodeHintType(int margin) {
		// 用于设置QR二维码参数
		Hashtable<EncodeHintType, Object> qrParam = new Hashtable<EncodeHintType, Object>();
		// 设置QR二维码的纠错级别——这里选择中等级别
		qrParam.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
		// 设置二维码边框的距离
		if(margin <= 0){
			margin = 0;
		}
		qrParam.put(EncodeHintType.MARGIN, margin);
		return qrParam;
	}
	
	
	/**
	 * 压缩logo
	 * @param image
	 * @param logoImage
	 */
	public static void compressLogoImage(BufferedImage image,Image logoImage){
		int w = image.getWidth();
		int h = image.getHeight();
		
		int width = logoImage.getWidth(null);
		int height = logoImage.getHeight(null);
		if (width > w) {  
            width = w;  
        }  
        if (height > h) {  
            height = h;  
        }  
        Image mImage = logoImage.getScaledInstance(width, height,Image.SCALE_SMOOTH);  
        BufferedImage tag = new BufferedImage(width, height,BufferedImage.TYPE_INT_RGB);  
        Graphics g = tag.getGraphics();  
        // 绘制缩小后的图
        g.drawImage(mImage, 0, 0, null);
        g.dispose();
        logoImage = mImage;
	}
}
